package com.netty;

import com.util.Gloabl;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;

/**
 * netty服务端
 * 
 * @author micro
 *
 */
public class NettyServer {

	public static void main(String[] args) {
		new NettyServer().run();
	}

	public void run() {
		try {
			// 1.创建两个线程池，一个负责接收客户端，一个进行传输。
			EventLoopGroup bossGroup = new NioEventLoopGroup();
			EventLoopGroup workerGroup = new NioEventLoopGroup();
			try {
				// 2.创建辅助类
				ServerBootstrap b = new ServerBootstrap();
				b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)//指定NIO的模式，如果是客户端就是NioSocketChannel
						.option(ChannelOption.SO_BACKLOG, 1024)//TCP的缓冲区设置
						// 3.设置缓冲区与发送区大小
						.option(ChannelOption.SO_SNDBUF, 32 * 1024)//设置发送缓冲的大小
						.option(ChannelOption.SO_RCVBUF, 32 * 1024)//设置接收缓冲区大小
						.option(ChannelOption.SO_KEEPALIVE, true)//保持连续
						.childHandler(new ChannelInitializer<SocketChannel>() {
							@Override
							public void initChannel(SocketChannel ch) throws Exception {
								/***** 解决粘包问题，用ByteBuf来做分隔符，有_mayi字符的就发，否则不发。(一般推荐这种方式) *****/
								// ByteBuf buf = Unpooled.copiedBuffer("_mayi".getBytes());
								// ch.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, buf));

								/***** 设置字符串 *****/
								// ch.pipeline().addLast(new StringDecoder());

								/***** 传对象 ******/
								// 用ObjectEncoder和ObjectDecoder.(网上参考传对象方式)
								//ch.pipeline().addLast(new ObjectEncoder(),
								//		new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null)),
								//		new NettyServerHandler());

								// 用序列化对象.(参考蚂蚁架构导师案例代码)
								ch.pipeline().addLast(
										MarshallingCodeCFactory.buildMarshallingDecoder(),
										MarshallingCodeCFactory.buildMarshallingEncoder(), 
										new NettyServerHandler());
							}
						});

				// 4.启动和关闭
				// 绑定端口，同步等待成功
				ChannelFuture f = b.bind(Gloabl.port).sync();

				// 等待服务端监听端口关闭
				f.channel().closeFuture().sync();
			} finally {
				// 优雅退出，释放线程池资源
				bossGroup.shutdownGracefully();
				workerGroup.shutdownGracefully();
			}
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("服务端异常：[" + e.getMessage() + "]");
		}
	}
}
